home *** CD-ROM | disk | FTP | other *** search
/ Aminet 6 / Aminet 6 - June 1995.iso / Aminet / dev / gui / js_tools123.lha / js_tools / demos / Demo_2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-27  |  21.1 KB  |  584 lines

  1. #include <exec/types.h>
  2. #include <proto/exec.h>
  3. #include <exec/memory.h>
  4. #include <proto/js_tools.h>
  5. #include <js_tools.h>
  6. #include <proto/intuition.h>
  7. #include <intuition/intuition.h>
  8. #include <proto/gadtools.h>
  9. #include <libraries/gadtools.h>
  10. #include <stdlib.h>
  11. #include <stdio.h>
  12. #include <stddef.h>
  13.  
  14. /*
  15.  * This is a short demo of the js_tools.library listview gadget.
  16.  * It opens a window on workbench and draws some listviews.
  17.  * This in no realy good code, its a DEMO CODE!
  18.  *
  19.  * js_tools.library is copyright (c) by J.Schmitz in 1995
  20.  * and may be free copied and used as freeware
  21.  *
  22.  * This Demo is copyright (c) by J.Schmitz in 1995
  23.  * and may be free copied and used with the js_tools.library distribution.
  24.  * Parts of the code may be used in own programs.
  25.  * Military use of js_tools.library or this demo if not allowed!
  26.  *
  27.  */
  28.  
  29. #define lvwidth     260
  30. #define lvheight    80
  31.  
  32.  
  33. /* Uhhh, global variables, my prof would kill me, */
  34. /* but theres is no better/easier way - and there will be no more! */
  35.  
  36. struct Library  *JS_ToolsBase;
  37. struct Library  *GadtoolsBase;
  38. struct IntuitionBase *IntuitionBase;
  39.  
  40. /* hm, a contant variable.... */
  41. /* I use topaz 8 because it's easier to do in a demo! */
  42. struct TextAttr ta={"topaz.font",8,0,0};
  43.  
  44.  
  45. /* here a struct for our texts */
  46. struct tnode {
  47.     struct Node n;
  48.     char        txt[60];
  49. };
  50.  
  51. /* here a struct for our multi column texts */
  52. struct tcnode {
  53.     struct Node n;
  54.     char        txt1[20];
  55.     char        txt2[20];
  56.     char        txt3[10];
  57. };
  58.  
  59. void FreeList(struct List *ls)
  60. {
  61.     struct Node *n;
  62.  
  63.     while (n=RemTail(ls))
  64.     {
  65.         FreeVec(n);
  66.     }
  67. }
  68.  
  69. void genText(struct List *ls,int nr)
  70. {
  71.     struct tnode *n;
  72.     int i;
  73.  
  74.     for (i=0;i<100;i++)
  75.     {
  76.         if (n=AllocVec(sizeof(struct tnode),MEMF_CLEAR))
  77.         {
  78.             sprintf(n->txt,"Line %d - LV %d",i,nr);
  79.             n->n.ln_Name=n->txt;
  80.             AddTail(ls,(struct Node*)n);
  81.         }
  82.     }
  83. }
  84. void genSPText(struct List *ls,int nr)
  85. {
  86.     struct tnode *n;
  87.     int i;
  88.  
  89.     for (i=0;i<100;i++)
  90.     {
  91.         if (n=AllocVec(sizeof(struct tnode),MEMF_CLEAR))
  92.         {
  93.             sprintf(n->txt,"Line %d - SuperListView gadget no. %d",i,nr);
  94.             n->n.ln_Name=n->txt;
  95.             AddTail(ls,(struct Node*)n);
  96.         }
  97.     }
  98. }
  99. void genCDText(struct List *ls,int nr)
  100. {
  101.     struct tcnode *n;
  102.     int i,j;
  103.  
  104.     for (i=0;i<100;i++)
  105.     {
  106.         if (n=AllocVec(sizeof(struct tcnode),MEMF_CLEAR))
  107.         {
  108.             j=(ULONG)n/(i+1);
  109.             sprintf(n->txt1,"Line %d",i);
  110.             sprintf(n->txt2,"in ListView %d",nr);
  111.             sprintf(n->txt3,"%d",j);
  112.             n->n.ln_Name=n->txt1;
  113.                 /* this is only if we would have a string gadget */
  114.             AddTail(ls,(struct Node*)n);
  115.         }
  116.     }
  117. }
  118.  
  119. struct Gadget *gen1(struct Gadget *gad,struct Window *win,APTR vi,struct List *ls)
  120. {
  121.     /* this is a 100% identical gadtools listview! */
  122.     /* but you better use a 100% js_tools listview! */
  123.  
  124.     struct NewGadget    ng;
  125.     struct TagItem      ti[]={
  126.         {lv_Labels,0},
  127.         {lv_ScrollWidth,20},
  128.         {lv_ShowSelected,0},
  129.         {lv_NewSelectMode,NSM_NoLine},  /* default is NSM_ExtraLine */
  130.         {TAG_DONE,0}
  131.         };
  132.  
  133.     ti[0].ti_Data=(ULONG)ls;
  134.     genText(ls,1);
  135.  
  136.     ng.ng_LeftEdge      =win->BorderLeft+5;
  137.     ng.ng_TopEdge       =win->TopEdge+3;
  138.     ng.ng_Width         =lvwidth;
  139.     ng.ng_Height        =lvheight;
  140.     ng.ng_GadgetText    =NULL; /* Currently not supported. Set to NULL! */
  141.     ng.ng_TextAttr      =&ta;
  142.     ng.ng_GadgetID      =1;
  143.     ng.ng_Flags         =0;
  144.     ng.ng_VisualInfo    =vi;
  145.     ng.ng_UserData      =NULL;
  146.     return LV_CreateListViewA(LISTVIEW1_KIND,gad,&ng,&ti[0]);
  147. }
  148. struct Gadget *gen2(struct Gadget *gad,struct Window *win,APTR vi,struct List *ls)
  149. {
  150.     /* this is a multiselection gadget with cursor key support! */
  151.  
  152.     struct NewGadget    ng;
  153.     struct TagItem      ti[]={
  154.         {lv_Labels,0},
  155.         {lv_ScrollWidth,20},
  156.         {lv_ShowSelected,0},
  157.         {lv_NewSelectMode,NSM_FreeLine},
  158.         {lv_NewSelectLines,3},
  159.         {lv_MarkOn,TRUE},
  160.         {TAG_DONE,0}
  161.         };
  162.  
  163.     ti[0].ti_Data=(ULONG)ls;
  164.     genText(ls,2);
  165.  
  166.     ng.ng_LeftEdge      =win->BorderLeft+5+5+lvwidth;
  167.     ng.ng_TopEdge       =win->TopEdge+3;
  168.     ng.ng_Width         =lvwidth;
  169.     ng.ng_Height        =lvheight;
  170.     ng.ng_GadgetText    =NULL; /* Currently not supported. Set to NULL! */
  171.     ng.ng_TextAttr      =&ta;
  172.     ng.ng_GadgetID      =2;
  173.     ng.ng_Flags         =0;
  174.     ng.ng_VisualInfo    =vi;
  175.     ng.ng_UserData      =NULL;
  176.     return LV_CreateListViewA(LISTVIEW1_KIND,gad,&ng,&ti[0]);
  177. }
  178. struct Gadget *gen3(struct Gadget *gad,struct Window *win,APTR vi,struct List *ls)
  179. {
  180.     /* this is a superlistview gadget */
  181.  
  182.     struct NewGadget    ng;
  183.     struct TagItem      ti[]={
  184.         {lv_Labels,0},
  185.         {lv_ScrollWidth,20},
  186.         {lv_ShowSelected,0},
  187.         {lv_SuperListView,TRUE},
  188.         {TAG_DONE,0}
  189.         };
  190.  
  191.     ti[0].ti_Data=(ULONG)ls;
  192.     genSPText(ls,3);
  193.  
  194.     ng.ng_LeftEdge      =win->BorderLeft+5;
  195.     ng.ng_TopEdge       =win->TopEdge+3+5+lvheight;
  196.     ng.ng_Width         =lvwidth;
  197.     ng.ng_Height        =lvheight;
  198.     ng.ng_GadgetText    =NULL; /* Currently not supported. Set to NULL! */
  199.     ng.ng_TextAttr      =&ta;
  200.     ng.ng_GadgetID      =3;
  201.     ng.ng_Flags         =0;
  202.     ng.ng_VisualInfo    =vi;
  203.     ng.ng_UserData      =NULL;
  204.     return LV_CreateListViewA(LISTVIEW1_KIND,gad,&ng,&ti[0]);
  205. }
  206. struct Gadget *gen4(struct Gadget *gad,struct Window *win,APTR vi,struct List *ls,struct ColumnData (*cd)[])
  207. {
  208.     /* this is a columned listview gadget, always marked when clicked */
  209.     /* but with other colours! */
  210.  
  211.     struct NewGadget    ng;
  212.     struct TagItem      ti[]={
  213.         {lv_Labels,0},
  214.         {lv_ColumnData,0},
  215.         {lv_ScrollWidth,20},
  216.         {lv_ShowSelected,0},
  217.         {lv_AlwaysMark,TRUE},
  218.         {lv_MarkOn,TRUE},
  219.         {TAG_DONE,0}
  220.         };
  221.  
  222.     ti[0].ti_Data=(ULONG)ls;
  223.     ti[1].ti_Data=(ULONG)cd;
  224.     genCDText(ls,4);
  225.  
  226.     /* first column, starts left, 60 pixels width */
  227.     (*cd)[0].cd_Offset  =(APTR)offsetof(struct tcnode,txt1);
  228.     (*cd)[0].cd_LeftEdge=0;
  229.     (*cd)[0].cd_Width   =60;
  230.     (*cd)[0].cd_Flags   =0;
  231.  
  232.     /* 2nd column, starts at pixel 65, 120 pixels width, text is centered */
  233.     (*cd)[1].cd_Offset  =(APTR)offsetof(struct tcnode,txt2);
  234.     (*cd)[1].cd_LeftEdge=65;
  235.     (*cd)[1].cd_Width   =120;
  236.     (*cd)[1].cd_Flags   =cdf_AdjustMid;
  237.     (*cd)[2].cd_Offset  =(APTR)offsetof(struct tcnode,txt3);
  238.  
  239.     /* 3rd column, starts at pixel 190, 50 pixels width, text is right adjusted */
  240.     (*cd)[2].cd_LeftEdge=190;
  241.     (*cd)[2].cd_Width   =50;
  242.     (*cd)[2].cd_Flags   =cdf_AdjustRight;
  243.  
  244.     /* end of ColumnData array marked with a NULL element */
  245.     (*cd)[3].cd_Offset  =NULL;
  246.     (*cd)[3].cd_LeftEdge=0;
  247.     (*cd)[3].cd_Width   =0;
  248.     (*cd)[3].cd_Flags   =0;
  249.  
  250.     ng.ng_LeftEdge      =win->BorderLeft+5+5+lvwidth;
  251.     ng.ng_TopEdge       =win->TopEdge+3+5+lvheight;
  252.     ng.ng_Width         =lvwidth;
  253.     ng.ng_Height        =lvheight;
  254.     ng.ng_GadgetText    =NULL; /* Currently not supported. Set to NULL! */
  255.     ng.ng_TextAttr      =&ta;
  256.     ng.ng_GadgetID      =4;
  257.     ng.ng_Flags         =0;
  258.     ng.ng_VisualInfo    =vi;
  259.     ng.ng_UserData      =NULL;
  260.     return LV_CreateListViewA(LISTVIEW2_KIND,gad,&ng,&ti[0]);
  261. }
  262. struct Gadget *genB(struct Gadget *gad,struct Window *win,APTR vi,char *txt,int x,int width,int nr)
  263. {
  264.     /* make a button */
  265.  
  266.     struct NewGadget    ng;
  267.  
  268.     ng.ng_LeftEdge      =win->BorderLeft+5+x;
  269.     ng.ng_TopEdge       =win->TopEdge+3+5+lvheight*2+4;
  270.     ng.ng_Width         =width;
  271.     ng.ng_Height        =12;
  272.     ng.ng_GadgetText    =txt;
  273.     ng.ng_TextAttr      =&ta;
  274.     ng.ng_GadgetID      =nr;
  275.     ng.ng_Flags         =PLACETEXT_IN;
  276.     ng.ng_VisualInfo    =vi;
  277.     ng.ng_UserData      =NULL;
  278.     return CreateGadgetA(BUTTON_KIND,gad,&ng,NULL);
  279. }
  280. struct Gadget *genT(struct Gadget *gad,struct Window *win,APTR vi,char *txt,int x,int width)
  281. {
  282.     /* make a button */
  283.  
  284.     struct NewGadget    ng;
  285.     struct TagItem      ti[]={
  286.         {GTTX_Text,0},
  287.         {GTTX_Border,TRUE},
  288.         {TAG_DONE,0}
  289.         };
  290.  
  291.     ti[0].ti_Data=(ULONG)txt;
  292.  
  293.     ng.ng_LeftEdge      =win->BorderLeft+5+x;
  294.     ng.ng_TopEdge       =win->TopEdge+3+5+lvheight*2+4;
  295.     ng.ng_Width         =width;
  296.     ng.ng_Height        =12;
  297.     ng.ng_GadgetText    =NULL;
  298.     ng.ng_TextAttr      =&ta;
  299.     ng.ng_GadgetID      =0;
  300.     ng.ng_Flags         =PLACETEXT_LEFT;
  301.     ng.ng_VisualInfo    =vi;
  302.     ng.ng_UserData      =NULL;
  303.     return CreateGadgetA(TEXT_KIND,gad,&ng,&ti[0]);
  304. }
  305. void textOut(struct Gadget *gad,struct Window *win,char *txt)
  306. {
  307.     struct TagItem ti[]={
  308.         {GTTX_Text,0},
  309.         {TAG_DONE,0},
  310.         };
  311.     ti[0].ti_Data=(ULONG)txt;
  312.     GT_SetGadgetAttrsA(gad,win,NULL,&ti[0]);
  313. }
  314.  
  315. void TheDemo(void)
  316. {
  317.     /* first, we need some (struct List) or (struct MinList) */
  318.     /* I take (struct List) in this demo because then I have so write */
  319.     /* no so much casts! */
  320.     struct List ls1,ls2,ls3,ls4;
  321.     struct ColumnData cd[4];
  322.  
  323.     struct Gadget       *glp=NULL,*gad;
  324.     APTR                vi=NULL;
  325.     struct Window       *win;
  326.     struct Screen       *scr;
  327.     struct Gadget       *lv1,*lv2,*lv3,*lv4,*txtgg;
  328.     struct IntuiMessage *my_MSG;
  329.     BOOL                ende=FALSE;
  330.     char                buffer[60];
  331.  
  332.     NewList(&ls1);
  333.     NewList(&ls2);
  334.     NewList(&ls3);
  335.     NewList(&ls4);
  336.  
  337.     /* well, because we have no own screen and I don't have the time */
  338.     /* to use this PublicScreen things, I open the window and read its */
  339.     /* WScreen. */
  340.  
  341.     if (win=OpenWindowTags(NULL,WA_Activate,TRUE,
  342.                                 WA_CloseGadget,TRUE,
  343.                                 WA_DepthGadget,TRUE,
  344.                                 WA_DragBar,TRUE,
  345.                                 WA_SmartRefresh,TRUE, /* it's a Demo, sorry :-) */
  346.                                 WA_IDCMP,LISTVIEWIDCMP|IDCMP_CLOSEWINDOW|IDCMP_RAWKEY,
  347.                                 WA_InnerWidth,lvwidth*2+5+5+5,
  348.                                 WA_InnerHeight,lvheight*2+3+3+5+12+4,
  349.                                 WA_Title,"js_tools Listview Demo",
  350.                                 TAG_DONE))
  351.     {
  352.         /* ah, our window is open! */
  353.         scr=win->WScreen;
  354.         if (vi=GetVisualInfoA(scr,NULL))
  355.         {
  356.             gad=CreateContext(&glp);
  357.             if (lv1=gen1(gad,win,vi,&ls1))
  358.             {
  359.                 gad=lv1;
  360.             }
  361.             if (lv2=gen2(gad,win,vi,&ls2))
  362.             {
  363.                 gad=lv2;
  364.             }
  365.             if (lv3=gen3(gad,win,vi,&ls3))
  366.             {
  367.                 gad=lv3;
  368.             }
  369.             if (lv4=gen4(gad,win,vi,&ls4,&cd))
  370.             {
  371.                 gad=lv4;
  372.             }
  373.             /* and finally we make 3 gadtools buttons */
  374.             gad=genB(gad,win,vi,"Quit",0,100,10);
  375.             gad=genB(gad,win,vi,"Lock",105,100,11);
  376.             gad=genB(gad,win,vi,"Unlock",210,100,12);
  377.             gad=genT(gad,win,vi,"by J.Schmitz",315,lvwidth*2+5+5-320);
  378.             txtgg=gad;
  379.  
  380.             AddGList(win,glp,~0,~0,NULL);
  381.             RefreshGList(glp,win,NULL,-1);
  382.             LV_RefreshWindow(win,NULL);
  383.  
  384.             do
  385.             {
  386.                 my_MSG=(struct IntuiMessage*)WaitPort(win->UserPort);
  387.                 my_MSG=LV_GetIMsg(win->UserPort);
  388.                 if (my_MSG)
  389.                 {
  390.                     switch (my_MSG->Class)
  391.                     {
  392.                         case IDCMP_CLOSEWINDOW:
  393.                             ende=TRUE;
  394.                             break;
  395.                         case IDCMP_GADGETUP:
  396.                         case IDCMP_GADGETDOWN:
  397.                             /*
  398.                              * the user selected something
  399.                              * we can find the number in my_MSG->Code
  400.                              * and the gadget in my_MSG->IAddress
  401.                              *
  402.                              * we have a DEMO, so I don't write here some
  403.                              * usefull code!
  404.                              * Only a example to show you the multiselection-
  405.                              * result for lv2. lv4 has to be handled the same way.
  406.                              *
  407.                              */
  408.                             gad=(struct Gadget*)my_MSG->IAddress;
  409.                             switch (gad->GadgetID)
  410.                             {
  411.                                 case 10:
  412.                                     ende=TRUE;
  413.                                     break;
  414.                                 case 11:
  415.                                     {
  416.                                         /* lock all listviews */
  417.                                         struct TagItem ti[]={
  418.                                             {lv_Disabled,TRUE},
  419.                                             {TAG_DONE,0},
  420.                                             };
  421.                                         LV_SetListViewAttrsA(lv1,win,NULL,&ti[0]);
  422.                                         LV_SetListViewAttrsA(lv2,win,NULL,&ti[0]);
  423.                                         LV_SetListViewAttrsA(lv3,win,NULL,&ti[0]);
  424.                                         LV_SetListViewAttrsA(lv4,win,NULL,&ti[0]);
  425.                                     }
  426.                                     break;
  427.                                 case 12:
  428.                                     {
  429.                                         /* unlock all listviews */
  430.                                         struct TagItem ti[]={
  431.                                             {lv_Disabled,FALSE},
  432.                                             {TAG_DONE,0},
  433.                                             };
  434.                                         LV_SetListViewAttrsA(lv1,win,NULL,&ti[0]);
  435.                                         LV_SetListViewAttrsA(lv2,win,NULL,&ti[0]);
  436.                                         LV_SetListViewAttrsA(lv3,win,NULL,&ti[0]);
  437.                                         LV_SetListViewAttrsA(lv4,win,NULL,&ti[0]);
  438.                                     }
  439.                                     break;
  440.                                 case 1:
  441.                                     sprintf(buffer,"Listview 1: %d",my_MSG->Code);
  442.                                     textOut(txtgg,win,buffer);
  443.                                     break;
  444.                                 case 2:
  445.                                     sprintf(buffer,"Listview 2: %d",my_MSG->Code,my_MSG->MouseY);
  446.                                     textOut(txtgg,win,buffer);
  447.  
  448.                                     if (my_MSG->Qualifier & MARK_QUALIFIER_SET)
  449.                                     {
  450.                                         /* aha, user made multiselection */
  451.                                         /* in a real program we have to look in */
  452.                                         /* my_MSG->MouseX for the top line of the marked block */
  453.                                         /* and in my_MSG->MouseY for the bottom line. */
  454.                                         /* Well, this is a DEMO, and you know... ;-) */
  455.  
  456.                                         sprintf(buffer,"Multi ON: %d - %d (Sel: %d)",my_MSG->MouseX,my_MSG->MouseY,my_MSG->Code);
  457.                                         textOut(txtgg,win,buffer);
  458.                                     }
  459.                                     if (my_MSG->Qualifier & MARK_QUALIFIER_CLEAR)
  460.                                     {
  461.                                         /* aha, user made multiOFFselection */
  462.                                         /* in a real program we have to look in */
  463.                                         /* my_MSG->MouseX for the top line of the marked block */
  464.                                         /* and in my_MSG->MouseY for the bottom line. */
  465.                                         /* Only a DEMO. */
  466.  
  467.                                         sprintf(buffer,"Multi OFF: %d - %d (Sel: %d)",my_MSG->MouseX,my_MSG->MouseY,my_MSG->Code);
  468.                                         textOut(txtgg,win,buffer);
  469.                                     }
  470.                                     /* OK, currently this seams to be a useless double way of checking bits */
  471.                                     /* but maybe in later releases of js_tools there would be more qualifiers! */
  472.                                     break;
  473.                                 case 3:
  474.                                     sprintf(buffer,"Listview 3: %d",my_MSG->Code);
  475.                                     textOut(txtgg,win,buffer);
  476.                                     break;
  477.                                 case 4:
  478.                                     if (my_MSG->Qualifier & MARK_QUALIFIER_SET)
  479.                                     {
  480.                                         /* aha, user made multiselection */
  481.                                         /* in a real program we have to look in */
  482.                                         /* my_MSG->MouseX for the top line of the marked block */
  483.                                         /* and in my_MSG->MouseY for the bottom line. */
  484.                                         /* Well, DEMO... ;-) */
  485.  
  486.                                         sprintf(buffer,"LV4 ON: %d - %d (Sel: %d)",my_MSG->MouseX,my_MSG->MouseY,my_MSG->Code);
  487.                                         textOut(txtgg,win,buffer);
  488.                                     }
  489.                                     if (my_MSG->Qualifier & MARK_QUALIFIER_CLEAR)
  490.                                     {
  491.                                         /* aha, user made multiOFFselection */
  492.                                         /* in a real program we have to look in */
  493.                                         /* my_MSG->MouseX for the top line of the marked block */
  494.                                         /* and in my_MSG->MouseY for the bottom line. */
  495.                                         /* This is a DEMO! */
  496.  
  497.                                         sprintf(buffer,"LV4 OFF: %d - %d (Sel: %d)",my_MSG->MouseX,my_MSG->MouseY,my_MSG->Code);
  498.                                         textOut(txtgg,win,buffer);
  499.                                     }
  500.                                     break;
  501.                             }
  502.                             break;
  503.                         case IDCMP_RAWKEY:
  504.                             {
  505.                                 struct TagItem ti[2];
  506.                                 ULONG sel;
  507.                                 int key;
  508.                                 ti[0].ti_Tag =lv_Selected;
  509.                                 ti[0].ti_Data=(ULONG)&sel;
  510.                                 ti[1].ti_Tag =TAG_DONE;
  511.                                 if ((key=LV_KeyHandler(lv2,my_MSG,0,&ti[0]))<0)
  512.                                 {
  513.                                     /* rawkey is used for listview */
  514.                                     /* now we can find the new selected item */
  515.                                     /* in sel */
  516.                                     /* well, lv2 is a multiselection listview */
  517.                                     /* so we have to check with lv_AskMarkNr if sel */
  518.                                     /* has been marked. */
  519.                                     /* But because this is a DEMO there is no real code */
  520.                                     /* for this!! */
  521.  
  522.                                     sprintf(buffer,"LV2: %d",sel);
  523.                                     textOut(txtgg,win,buffer);
  524.                                 }
  525.                                 else
  526.                                 {
  527.                                     /* key contains the ASCII value of the pressed key */
  528.                                     /* or 0 if no ASCII value is available. */
  529.  
  530.                                     sprintf(buffer,"Key pressed: %c (#%d)",key,key);
  531.                                     textOut(txtgg,win,buffer);
  532.                                     if (key==27)
  533.                                     {
  534.                                         ende=TRUE;
  535.                                     }
  536.                                 }
  537.                             }
  538.                             break;
  539.                     }
  540.                     LV_ReplyIMsg(my_MSG);
  541.                 }
  542.             }
  543.             while (!ende);
  544.  
  545.             RemoveGList(win,glp,~0);
  546.             LV_FreeListViews(glp);  /* this removed all listviews in this gadget list */
  547.                 /* ATTENTION! There is also a LV_FreeListView() without "s" to remove 1 listview */
  548.                 /*            But this should only be used for lvExtraWindow or for all listviews in a window */
  549.                 /*            e.g. if (lv4) LV_FreeListView(lv4); */
  550.                 /*                 if (lv3) LV_FreeListView(lv3); */
  551.                 /*             and so on */
  552.             FreeGadgets(glp);
  553.             FreeVisualInfo(vi);
  554.         }
  555.         CloseWindow(win);
  556.     }
  557.     FreeList(&ls4);
  558.     FreeList(&ls3);
  559.     FreeList(&ls2);
  560.     FreeList(&ls1);
  561. }
  562.  
  563. void main(void)
  564. {
  565.     if (JS_ToolsBase=OpenLibrary("js_tools.library",37))
  566.     {
  567.         /* yea, we got it! */
  568.         if (GadtoolsBase=OpenLibrary("gadtools.library",37))
  569.         {
  570.             if (IntuitionBase=(struct IntuitionBase*)OpenLibrary("intuition.library",37))
  571.             {
  572.                 /* everything is fine, now, let's start! */
  573.  
  574.                 TheDemo();
  575.  
  576.                 CloseLibrary((struct Library*)IntuitionBase);
  577.             }
  578.             CloseLibrary(GadtoolsBase);
  579.         }
  580.         CloseLibrary(JS_ToolsBase);
  581.     }
  582. }
  583.  
  584.